package tcln.gxtx.client.utils.collection;

import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import com.extjs.gxt.ui.client.core.FastMap;
import com.google.gwt.core.client.GWT;

/**
 * An speed-optimized ordered map in client-side. This optimization relies on the fact that a JS map is indeed an
 * ordered map, just like {@link LinkedHashMap} in Java world. Thus, wherever possible, use JS implementation instead of
 * the simulated one.
 * 
 * @param <V>
 *            Value type.
 * @author Truong Chau Lien Ngoc (lienngoc@gmail.com)
 */
public class FastOrderedMap<V> implements Map<String, V>, Serializable {
    private static final long serialVersionUID = 1L;

    private Map<String, V> innerMap;

    /**
     * default constructor.
     */
    public FastOrderedMap() {
        if (GWT.isScript()) {
            innerMap = new FastMap<V>();
        } else {
            innerMap = new LinkedHashMap<String, V>();
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void clear() {
        innerMap.clear();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean containsKey(Object key) {
        return innerMap.containsKey(key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean containsValue(Object value) {
        return innerMap.containsValue(value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set<java.util.Map.Entry<String, V>> entrySet() {
        return innerMap.entrySet();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public V get(Object key) {
        return innerMap.get(key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isEmpty() {
        return innerMap.isEmpty();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set<String> keySet() {
        return innerMap.keySet();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public V put(String key, V value) {
        return innerMap.put(key, value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void putAll(Map<? extends String, ? extends V> map) {
        innerMap.putAll(map);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public V remove(Object key) {
        return innerMap.remove(key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int size() {
        return innerMap.size();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<V> values() {
        return innerMap.values();
    }

}
